// ml278
// Copyright (C) 2008 Bjørn Øivind Bjørnsen, Aleksander Gjermundsen, Knut Andre Tidemann, Thomas Hansen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

#ifndef __PLANETARYZONERENDERABLE_H_
#define __PLANETARYZONERENDERABLE_H_

#include <OgreMaterialManager.h>
#include <OgreRenderable.h>
#include <OgreMovableObject.h>

namespace Ogre
{
	class PlanetarySceneManager;
	class PlanetaryOptions;
	class PlanetaryZone;

	/**
	 * Implementation of a zone-level renderable.
	 * Implements Renderable and MovableObject, is what actually gets seen (vertex and index data is written here).
	*/
	class PlanetaryZoneRenderable : public Renderable, public MovableObject
	{
	public:
		PlanetaryZoneRenderable(PlanetarySceneManager *mgr);
		~PlanetaryZoneRenderable();

		void init(unsigned int zone,PlanetaryZone *parent);
		void load();
		void unload();
		void uninit();

		void setMaterial(MaterialPtr mat);

		// MovableObject overridden methods
		virtual void _notifyCurrentCamera(Camera* cam);
		virtual void _notifyAttached(Node* parent, bool isTagPoint = false);

		virtual void _updateRenderQueue(RenderQueue* queue);
		virtual void getRenderOperation(RenderOperation& rend);

		virtual const String &getMovableType() const
		{
			return mType;
		}

		virtual const AxisAlignedBox &getBoundingBox() const
		{
			return mBounds;
		}
		virtual Real getBoundingRadius() const
		{
			return mBoundingRadius;
		}


		// Renderable overridden methods
		virtual const MaterialPtr &getMaterial() const
		{
			return mMaterial;
		}

		virtual void getWorldTransforms(Matrix4 *xform) const;
		virtual const Quaternion &getWorldOrientation() const;
		virtual const Vector3 &getWorldPosition() const;
		virtual Real getSquaredViewDepth(const Camera *cam) const;
		virtual const LightList &getLights() const;

	protected:
		void loadUp(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize);
		void loadDown(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize);
		void loadFront(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize);
		void loadBack(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize);
		void loadLeft(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize);
		void loadRight(const VertexElement* poselem, uchar *pBuffer,unsigned int vertexSize);
		
		/// Scale of the terrain (planet radius)
		Real mScale;

		/// index the of the planet this renderable belongs to
		unsigned int mPlanet;
		/// index of the zone this renderable belongs to
		unsigned int mZone;

		/// Scene manager object
		PlanetarySceneManager *mSceneMgr;

		/// Options object
		PlanetaryOptions *mOptions;

		/// Parent page this renderable belongs to
		PlanetaryZone *mParent;

		/// Vertex data info
		VertexData *mVertices;

		/// Index data info
		IndexData *mIndices;

		/// MovableObject bounds
		AxisAlignedBox mBounds;

		/// MovableObject bounding radius
		Real mBoundingRadius;

		/// MovableObject type
		static String mType;

		/// Renderable material
		MaterialPtr mMaterial;

		/// Renderable center
		Vector3 mCenter;

		/// Whether light list need to re-calculate
		mutable bool mLightListDirty;

		/// Cached light list
		mutable LightList mLightList;

		/// true if the renderable if loaded
		bool mIsLoaded;
		/// true if the renderable has been initialised
		bool mIsInit;
	};
}

#endif
